package com.kayak.kboot.dao.kSql;

import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;

import com.alibaba.druid.pool.DruidDataSource;
import com.kayak.exception.ErrorException;
import com.kayak.kboot.web.sys.SysUtil;
import com.kayak.kkutils.Tools;

public class SqlStatement {
	
	public  int BATCH_COMMIT_UNIT=100;
	private static Boolean	FILL_NONE	= null;
	public static Boolean getFillNone() {
		if (FILL_NONE == null) {
			FILL_NONE = Tools.str2Boolean( "true");
		}
		return FILL_NONE;
	}


	private static Logger	log			= LoggerFactory.getLogger(SqlStatement.class.getName());

	private StringBuilder	sbSql;

	/**
	 * 分页查询时使用：查询起始行数
	 */
	private Integer			start		= null;

	/**
	 * 分页查询时使用：查询返回行数
	 */
	private Integer			limit		= null;

	private List<String>	sort		= null;

	private List<String>	dir			= null;

	private JdbcTemplate	jdbc		= null;
	
	private String dbType="";
	private String dbName="";


	/**
	 * 创建SqlStatement实例用以执行SQL语句
	 *
	 * @param sql
	 *            要执行的SQL语句
	 * @throws ErrorException
	 */
	public SqlStatement(String sql, JdbcTemplate jdbc) throws ErrorException,
			SQLException {
		if (Tools.strIsEmpty(sql))
			throw new ErrorException("创建SqlStatement实例的SQL语句不能为空。");
		if (jdbc == null)
			throw new ErrorException("创建SqlStatement实例的JdbcTemplate对象不能为空。");
		this.jdbc = jdbc;
		this.dbType=((DruidDataSource)this.jdbc.getDataSource()).getDbType();
		this.dbName=((DruidDataSource)this.jdbc.getDataSource()).getName();
		this.sbSql = new StringBuilder(sql);
		
	}

	/**
	 * 检查参数有效性
	 */
	private static boolean checkPara(String paraName, Object paraValue) {
		if (paraName == null) {
			log.error("paraName is null");
			return false;
		}
		if (paraValue == null) {
			// log.error("paraValue is null");
			// return false;
		}
		return true;
	}

	private static final String	String		= "S";
	private static final String	Number		= "N";
	private static final String	Unknow		= "U";
	private static final String	IsNull		= "ISNULL";
	private static final String	IsNotNull	= "ISNOTNULL";
	private static final String	UUID	    = "UUID";
	//private static final String	DATE	    = "DATE";
	//private static final String	TIME	    = "TIME";
	//private static final String	DATETIME	= "DATETIME";

	
	
	
	/**
	 * 替换参数值<br />
	 * 填充在SQL语句里以$类型{变量名}形式占位的变量为实际参数值
	 *
	 * @param sb
	 *            StringBuilder 要替换参数的SQL语句
	 * @param paraName
	 *            参数名（即变量名）
	 * @param sqlValue
	 *            可直接接入到SQL语句里的参数值
	 * @param paraType
	 *            参数类型：<br />
	 *            "AUTOID" - 自动生成的ID值，此类型只能用于INSERT语句，用于自动生成唯一ID，<br />
	 *            "N" - 数字类型（包括：Integer,Long,Short,Double,BifDecimal），<br />
	 *            "S" - 字符串类型（String），<br />
	 *            "U" - 未知类型，将直接把参数值输出到SQL语句中，<br />
	 *            "ISNULL" - 判断该参数值是否为空（字符型:null或"",
	 *            数字型:null)，如果是，则用1=1替代，否则用1=0替代<br />
	 *            "ISNOTNULL" - 判断该参数值是否不为空（字符型:null或"",
	 *            数字型:null)，如果不为空，则用1=1替代，否则用1=0替代
	 */
	private static void replacePara(final StringBuilder sql, String paraName, String sqlValue, String paraType) {
		Pattern ptn = Pattern.compile("[$]" + paraType + "\\{" + paraName+ "\\}", Pattern.CASE_INSENSITIVE);
		Matcher matcher = ptn.matcher(sql);
		while (matcher.find()) {
			sql.replace(matcher.start(), matcher.end(), sqlValue);
			matcher.reset(sql);// 因为matcher的字符串改变了，所以要重新matcher
		}
	}

	/**
	 * 设置Integer类型参数值
	 */
	public void setInteger(String paraName, Integer paraValue) {
		if (checkPara(paraName, paraValue)) {
			replacePara(this.sbSql, paraName, paraValue.toString(), Number);
		}
	}

	/**
	 * 设置未知类型数组参数值，把所有数组元素用逗号拼凑起来后直接输出到SQL语句中
	 */
	public void setInUnknowParam(String paraName, Object[] paraValues) {
		setInUnknowParam(this.sbSql, paraName, paraValues);
	}

	/**
	 * 设置未知类型数组参数值，把所有数组元素用逗号拼凑起来后直接输出到SQL语句中
	 */
	public static void setInUnknowParam(final StringBuilder sql,String paraName, Object[] paraValues) {
		if (checkPara(paraName, paraValues)) {
			if (paraValues == null || paraValues.length == 0) {// 数组为0，为了避免SQL语句执行出错，填充一个空值
				replacePara(sql, paraName, SqlUtil.sqlString(""), String);
				return;
			}
			StringBuffer sb = new StringBuffer();
			for (Object val : paraValues) {
				sb.append(",").append(SqlUtil.str2query(val.toString()));
			}
			replacePara(sql, paraName, sb.substring(1), Unknow);
		}
	}

	/**
	 * 设置不是输出到SQL语句的参数变量（直接把变量值输出，不过滤单引号）
	 */
	public static void setNot2SqlParam(final StringBuilder sb, String paraName,
			Object paraValue, String paraType) {
		if (checkPara(paraName, paraValue)) {
			replacePara(sb, paraName, Tools.trimString(paraValue), paraType);
		}
	}

	/**
	 * 设置不是输出到SQL语句的数组参数变量（直接把变量值输出，不过滤单引号）
	 */
	public static void setNot2SqlParam(final StringBuilder sql,
			String paraName, Object[] paraValues, String paraType) {
		if (checkPara(paraName, paraValues)) {
			if (paraValues == null || paraValues.length == 0) {// 数组为0，填充一个空值
				replacePara(sql, paraName, "", paraType);
				return;
			}
			StringBuffer sb = new StringBuffer();
			for (Object val : paraValues) {
				sb.append(",").append(val);
			}
			replacePara(sql, paraName, sb.substring(1), paraType);
		}
	}

	/**
	 * 设置未知类型参数值，直接把变量值输出到SQL语句中
	 */
	public void setUnknowParam(String paraName, Object paraValue) {
		setUnknowParam(this.sbSql, paraName, paraValue);
	}

	/**
	 * 设置未知类型参数值，直接把变量值输出到SQL语句中
	 */
	public static void setUnknowParam(final StringBuilder sql, String paraName,
			Object paraValue) {
		if (checkPara(paraName, paraValue)) {
			replacePara(sql, paraName,
					SqlUtil.str2query(Tools.trimString(paraValue)), Unknow);
		}
	}


	/**
	 * 设置String类型参数值
	 */
	public void setString(String paraName, String paraValue) {
		setString(this.sbSql, paraName, paraValue);
	}

	/**
	 * 设置String类型参数值
	 */
	public static void setString(final StringBuilder sql, String paraName,
			String paraValue) {
		if (checkPara(paraName, paraValue)) {
			replacePara(sql, paraName, SqlUtil.sqlString(paraValue), String);
		}
	}


	/**
	 * 设置Long类型参数值
	 */
	public void setLong(String paraName, Long paraValue) {
		setLong(this.sbSql, paraName, paraValue);
	}

	/**
	 * 设置Long类型参数值
	 */
	public static void setLong(final StringBuilder sql, String paraName,
			Long paraValue) {
		if (checkPara(paraName, paraValue)) {
			replacePara(sql, paraName, paraValue.toString(), Number);
		}
	}

	/**
	 * 设置Short类型参数值
	 */
	public void setShort(String paraName, Short paraValue) {
		if (checkPara(paraName, paraValue)) {
			replacePara(this.sbSql, paraName, paraValue.toString(), Number);
		}
	}

	/**
	 * 设置Double类型参数值
	 */
	public void setDouble(String paraName, Double paraValue) {
		if (checkPara(paraName, paraValue)) {
			replacePara(this.sbSql, paraName, paraValue.toString(), Number);
		}
	}

	/**
	 * 设置BigDecimal类型参数值
	 */
	public void setBigDecimal(String paraName, BigDecimal paraValue) {
		setBigDecimal(this.sbSql, paraName, paraValue);
	}

	/**
	 * 设置BigDecimal类型参数值
	 */
	public static void setBigDecimal(final StringBuilder sql, String paraName,
			BigDecimal paraValue) {
		if (checkPara(paraName, paraValue)) {
			replacePara(sql, paraName, paraValue.toString(), Number);
		}
	}

	/**
	 * 设置使用在SQL的in语句里的多个字符串参数值<br />
	 *
	 * @param paraName
	 *            参数名称
	 * @param paraValues
	 *            字符串参数值数组
	 */
	public void setInString(String paraName, String[] paraValues) {
		setInString(this.sbSql, paraName, paraValues);
	}

	/**
	 * 设置使用在SQL的in语句里的多个字符串参数值<br />
	 *
	 * @param paraName
	 *            参数名称
	 * @param paraValues
	 *            字符串参数值数组
	 */
	public static void setInString(final StringBuilder sql, String paraName,
			Object[] paraValues) {
		if (checkPara(paraName, paraValues)) {
			if (paraValues == null || paraValues.length == 0) {// 数组为0，为了避免SQL语句执行出错，填充一个空值
				replacePara(sql, paraName, SqlUtil.sqlString(""), String);
				return;
			}
			StringBuffer sb = new StringBuffer();
			for (Object val : paraValues) {
				sb.append(",").append(SqlUtil.sqlString(val.toString()));
			}
			replacePara(sql, paraName, sb.substring(1), String);
		}
	}

	/**
	 * 设置使用在SQL的in语句里的多个整数参数值<br />
	 *
	 * @param paraName
	 *            参数名称
	 * @param paraValues
	 *            整数参数值数组
	 */
	public void setInInteger(StringBuilder sql, String paraName,
			Integer[] paraValues) {
		if (checkPara(paraName, paraValues)) {
			if (paraValues.length == 0) {// 数组为0，为了避免SQL语句执行出错，填充一个0
				replacePara(sql, paraName, "0", Number);
				return;
			}
			StringBuffer sb = new StringBuffer();
			for (Integer val : paraValues) {
				sb.append(",").append(val);
			}
			replacePara(sql, paraName, sb.substring(1), Number);
		}
	}

	/**
	 * 设置使用在SQL的in语句里的多个数字参数值<br />
	 *
	 * @param paraName
	 *            参数名称
	 * @param paraValues
	 *            数字参数值数组
	 * @throws SqlException
	 */
	public static void setInNumber(final StringBuilder sql, String paraName,
			Object[] paraValues) throws SqlException {
		if (checkPara(paraName, paraValues)) {
			if (paraValues == null || paraValues.length == 0) {// 数组为0，为了避免SQL语句执行出错，填充一个0
				replacePara(sql, paraName, "0", Number);
				return;
			}
			StringBuffer sb = new StringBuffer();
			for (Object val : paraValues) {
				String v = val.toString();
				if (Tools.isNumber(v))// 是否有效果数字字符
					sb.append(",").append(v);
			}
			if (sb.length() > 1)
				replacePara(sql, paraName, sb.substring(1), Number);
			else
				throw new SqlException("SQL语句参数" + paraName + "的值无效");
		}
	}

	/**
	 * 收集重复SQL语句
	 */
	private List<String>	repeatSqls;

	/**
	 * 添加参数到params集合中，如果pname在pamras中已存在，则把已存在的值与新添加的值组成数组（把新添加的值添加到原值后面）存放
	 *
	 * @param params
	 * @param pname
	 * @param value
	 */
	private static void addValue2params(final Map<String, Object> params,
			String pname, Object value) {
		if (params == null)
			return;

		Object obj = params.get(pname);
		if (obj == null) {
			obj = value;
		} else {
			List<Object> lst = new ArrayList<Object>();
			if (obj.getClass().isArray()) {
				Object[] objs = (Object[]) obj;
				for (Object o : objs) {
					lst.add(o);
				}
			} else {
				lst.add(obj);
			}
			lst.add(value);
			obj = lst.toArray();
		}
		params.put(pname, obj);
	}


	private static final Pattern	patternParam			= Pattern.compile("[$]([a-zA-Z0-9]+)\\{([\\w]+)\\}");

	private static final Pattern	patternAutoidParamName	= Pattern
																	.compile("([\\w]+)[,]([\\d]+)");

	/**
	 * 自动填充实例中SQL语句中的变量值<br />
	 * 执行的处理是从SQL是提取变量名，在params中取得变量值来填充<br />
	 * 如果在params中找不到变量值，则该变量将不被处理
	 *
	 * @param params
	 *            用于填充变量的参数集合
	 * @throws SqlException
	 * @throws ErrorException
	 */
	public void autoSetParams(Map<String, Object> params) throws SqlException,
			ErrorException {
		autoSetParams(params, true);
		log.info("["+this.dbName+"]["+this.dbType+"]sql:"+this.sbSql);
	}

	/**
	 * 自动填充实例中SQL语句中的变量值<br />
	 * 执行的处理是从SQL中提取变量名，在params中取得变量值来填充<br />
	 * 如果在params中找不到变量值，则该变量将不被处理
	 *
	 * @param params
	 *            用于填充变量的参数集合
	 * @param paging
	 *            是否设置分页参数，默认为true
	 * @throws SqlException
	 * @throws ErrorException
	 */
	public void autoSetParams(final Map<String, Object> params, boolean paging)
			throws SqlException, ErrorException {
		if (params != null) {// 如果没有传params参数，则不处理：分页，排序，重复串
			if (paging && params.get("start") != null
					&& params.get("limit") != null) {// 自动设置分页信息
				this.start = Tools.str2Int(params.get("start").toString());
				this.limit = Tools.str2Int(params.get("limit").toString());
			}
			if (params.get("sort") != null) {// 自动设置排序信息
				this.setSort(params.get("sort"));
				if (params.get("dir") != null) {
					this.setDir(params.get("dir"));
				}
			}
		}// end if params!=null
		autoSetParams(this.sbSql, params);
	}

	/**
	 * 自动注入参数值到SQL语句中
	 *
	 * @param sql
	 * @param params
	 * @throws SqlException
	 * @throws ErrorException
	 */
	public static void autoSetParams(final StringBuilder sql,
			final Map<String, Object> params) throws SqlException,
			ErrorException {
		autoSetParams(sql, params, true);
	}

	/**
	 * 自动注入参数值到字符串中
	 *
	 * @param sql
	 *            要注入的字符串
	 * @param params
	 *            提供注入的参数集
	 * @param toSql
	 *            注入的字符串是否作为SQL语句使用
	 * @throws SqlException
	 * @throws ErrorException
	 */
	public static void autoSetParams(final StringBuilder sql,
			final Map<String, Object> params, boolean toSql)
			throws SqlException, ErrorException {
		matcherProcess(patternParam, sql, params, toSql);
	}

	/**
	 * 根据正则处理注入参数值
	 *
	 * @param sql
	 *            要注入的字符串
	 * @param params
	 *            提供注入的参数集
	 * @param toSql
	 *            注入的字符串是否作为SQL语句使用
	 * @throws SqlException
	 * @throws ErrorException
	 */
	private static void matcherProcess(final Pattern pattern,
			final StringBuilder sql, final Map<String, Object> params,
			boolean toSql) throws SqlException, ErrorException {
		Matcher matcher = pattern.matcher(sql);
		while (matcher.find()) {
			String type = matcher.group(1); // 参数类型
			String pName = matcher.group(2).trim();// 参数名称
			boolean replaced = false;// 标识sql是否有被改动，如果有根据此标识需要matcher.reset
			if (!"".equals(pName)) {
				
					Object val = null;
					if (params != null)
						val = params.get(pName);
					
					if (val == null)// 取不到参数值，尝试从系统动态参数中取值
						val = SysUtil.getSysDynamicParamValue(pName, params);

					if (val != null
							|| (params != null && params.containsKey(pName))) {
						boolean isarray = false;
						if (val != null)
							isarray = val.getClass().isArray();

						replaced = true;

						if (!toSql) {// 不是注入到SQL语句的参数值，特殊用法
							if (isarray) {
								setNot2SqlParam(sql, pName, (Object[]) val,
										type);
							} else {
								setNot2SqlParam(sql, pName, (Object) val, type);
							}
						} else if (Unknow.equalsIgnoreCase(type)) {// 未知类型，直接输出内容
							if (isarray) {
								setInUnknowParam(sql, pName, (Object[]) val);
							} else {
								setUnknowParam(sql, pName, (Object) val);
							}
						} else if (String.equalsIgnoreCase(type)) {
							if (isarray) {// String[]字符串数组
								setInString(sql, pName, (Object[]) val);
							} else {// 字符串
								setString(sql, pName, Tools.trimString(val));
							}
						} else if (Number.equalsIgnoreCase(type)) {
							if (isarray) {// 数组
								setInNumber(sql, pName, (Object[]) val);
							} else {// 数字
								setBigDecimal(sql, pName,
										Tools.str2BigDecimal(Tools
												.trimString(val)));
							}
						}

						else if (IsNull.equalsIgnoreCase(type)) {// 注入变量值是否为空的判断
							String value;
							if (val == null || "".equals(Tools.trimString(val))) {// 变量值为空，注入1=1
								value = "1=1";
							} else {// 变量值不为空，注入1=0
								value = "1=0";
							}
							replacePara(sql, pName, value, IsNull);
						} else if (IsNotNull.equalsIgnoreCase(type)) {// 注入变量值是否不为空的判断
							String value;
							if (val == null || "".equals(Tools.trimString(val))) {// 变量值为空，注入1=0
								value = "1=0";
							} else {// 变量值不为空，注入1=1
								value = "1=1";
							}
							replacePara(sql, pName, value, IsNotNull);
						}  else {
							replaced = false;
							log.error("不能识别的参数类型：$" + type + "{" + pName + "}");
						}
					} 
			} 
			if (replaced)
				matcher.reset(sql);// 因为matcher的字符串改变了，所以要重新matcher
		}// end while
	}


	/**
	 * 分页查询时使用：设置查询起始行
	 */
	public void setStart(int num) {
		this.start = new Integer(num);
	}

	/**
	 * 分页查询时使用：设置查询返回行数
	 */
	public void setLimit(int num) {
		this.limit = new Integer(num);
	}

	/**
	 * 返回是否有分页设置（即设置了start和limit两个值）
	 */
	public boolean isPaging() {
		return start != null && start > -1 && limit != null && limit > 0;
	}


	/**
	 * 返回查询的SQL语句<br />
	 * （如果有分页设置，则返回的SQL语句里包括自动添加的分页代码）<br />
	 * 目前分页支持db2, oracle, mysql，如果需要使用在其它数据库上，请在这个方法里添加相关实现
	 */
	public String getQueryString() {
		if (isPaging()) {// 有分页
			int limit = this.start + this.limit;
			int start = this.start + 1;
			StringBuilder sb = new StringBuilder();
			if ("db2".equalsIgnoreCase(this.dbType)) {
				sb.append(
						"SELECT * from (SELECT rownumber() over() as rownumPageSql,pageSqlTemp.* from (")
						.append(setOrderString(sbSql.toString()))
						.append(") pageSqlTemp)pageSqlTemp2 where pageSqlTemp2.rownumPageSql between ")
						.append(start).append(" and ").append(limit);
			} else if ("oracle".equalsIgnoreCase(this.dbType)) {
				sb.append(
						"SELECT * from (SELECT rownum as rownumPageSql,pageSqlTemp.* from (")
						.append(setOrderString(sbSql.toString()))
						.append(") pageSqlTemp)pageSqlTemp2 where pageSqlTemp2.rownumPageSql between ")
						.append(start).append(" and ").append(limit);
			} else if ("mysql".equalsIgnoreCase(this.dbType)) {
				sb.append("SELECT * FROM (")
						.append(setOrderString(sbSql.toString()))
						.append(") pageTab limit ").append(this.start)
						.append(",").append(this.limit);
			} else {
				sb = sbSql;
			}
			return sb.toString();
		}
		return this.sbSql.toString();
	}

	private String setOrderString(String sql) {
		if (this.sort != null && this.sort.size() > 0) {
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < this.sort.size(); i++) {
				if (i > 0)
					sb.append(",");

				String cm = this.sort.get(i);
				sb.append(cm);
				if (this.dir != null && this.dir.size() > i) {
					sb.append(" ").append(this.dir.get(i));
				}
			}
			return " SELECT * FROM ( " + sql + " ) t ORDER BY " + sb;
		}
		return sql;
	}

	/**
	 * 返回查询总记录数的SQL语句
	 */
	public String getCountQueryString() {
		String countSql = " SELECT COUNT(1) FROM ( " + sbSql + " ) t ";
		log.info(countSql);
		return countSql;
	}

	/**

	/**
	 * 返回总记录数
	 */
	public long executeCountQuery() throws SQLException {
		if (this.jdbc != null) {
			SqlRowSet result = this.jdbc.queryForRowSet(this
					.getCountQueryString());
			if (result.next()) {
				return Long.valueOf(result.getObject(1).toString());
			}
		} 
		return 0;
	}

	/**
	 * 检查Sql语句中的参数是否全部已设置，如果不是，则抛出错误
	 *
	 * @throws SqlException
	 */
	public static void checkParamFilling(final StringBuilder sql)
			throws SqlException {
		// 从全局配置文件中读取未注入参数处理方式
		boolean fillNone = getFillNone();

		List<String> paramsName = null;
		Map<String, Object> paramsMap = null;
		if (fillNone) {// 如果需要注入空参数，则用pms生成空参数集
			paramsMap = new HashMap<String, Object>();
		} else {// 如果不需要注入空参数，则收集未设置的参数名称，用于提示错误
			paramsName = new ArrayList<String>();// 未设置的参数名称包括$符和大括号集合
		}
		Matcher matcher = patternParam.matcher(sql);
		while (matcher.find()) {
			if (fillNone) {// 如果需要注入空参数，收集参数名称，生成空参数集
				String pname = matcher.group(2).trim();// 参数名称
				paramsMap.put(pname, "");
			} else {
				String lname = sql.substring(matcher.start(), matcher.end()); // 包括类型的名称
				if (!paramsName.contains(lname))
					paramsName.add(lname);
			}
		}
		if (fillNone) {// 为未注入的参数填空值
			try {
				autoSetParams(sql, paramsMap);
			} catch (ErrorException e) {
				e.printStackTrace();
			}
		} else if (paramsName != null && paramsName.size() > 0) {// 直接报错
			log.error("==================== SQL Statement ====================\n"
					+ sql);
			throw new SqlException("SQL语句的 " + Tools.listJoin(paramsName)
					+ " 参数未设置");
		}
	}

	/**
	 * 执行查询操作并返回SqlResult类型查询结果实例<br />
	 * <b>注：查询SQL不支持重复statement</b>
	 */
	public SqlResult executeQuery() throws SqlException, SQLException {
		// 检查参数设置
		checkParamFilling(this.sbSql);

		SqlResult result;
		if (jdbc != null) {
			SqlRowSet rowSet = jdbc.queryForRowSet(this.getQueryString());
			result = new SqlResult(rowSet);
		}  else {
			throw new SqlException("SqlStatement对象的jdbc或statement为空");
		}

		// 给查询结果实列设置总记录数值
		if (isPaging()) {// 如果有分页，则需要另外查询总记录数
			result.setCount(executeCountQuery());
		} else {// 没有分页，则返回结果集的记录数就是总记录数
			result.setCount(result.getRowSize());
		}

		return result;
	}

	/**
	 * 执行更新操作
	 *
	 * @return 普通更新操作，则返回更新的记录数<br />
	 *         如果出现多SQL语句重复拼凑（$REPEAT[][][]的第三个中括号内值为statement）时<br />
	 *         将批量执行重复的SQL语句，并且返回执行的SQL语句数
	 * @throws SqlException
	 * @throws SQLException
	 */
	public int executeUpdate() throws SqlException, SQLException {
			checkParamFilling(this.sbSql);
			String updateSql = this.sbSql.toString().trim();
			if (Tools.strIsEmpty(updateSql)) {// sql语句为空，直接返回0
				return 0;
			}
			// 执行SQL更新，并返回更新的行数
			if (jdbc != null) {
				return this.jdbc.update(updateSql);
			} else {
				throw new SqlException("SqlStatement对象的jdbc或statement为空");
			}
	}
	
	public int batchUpdateInITransaction(List<Map<String,Object>> list ) throws SqlException, SQLException, ErrorException{
		return  this.batchUpdateInITransaction(list, true);
	}
	
	
	public int batchUpdateInITransaction(List<Map<String,Object>> list,boolean needBatchSqlPrint ) throws SqlException, SQLException, ErrorException{
		List<String> sqlList=new ArrayList<String>();
		String cachedSql=this.sbSql.toString();
		log.info("[begin batch update],oriSql:"+cachedSql);
		for(Map<String,Object> temp:list){
			autoSetParams(temp);
			checkParamFilling(this.sbSql);
			String updateSql =this.sbSql.toString().trim();
			if(needBatchSqlPrint){
				log.info(updateSql);
			}
			if (Tools.strIsEmpty(updateSql)) {// sql语句为空，直接返回0
				return 0;
			}
			sqlList.add(updateSql);
			sbSql=new StringBuilder(cachedSql);
		}
		
		int totalResult=0;
		
		int i=0;
		int[] ret={};
		log.info("[ori list size]:"+sqlList.size());
		while(true){
			
//			if(sqlList.size()<2000){
//				throw new ErrorException("人为退出测试");
//			}
			log.info("[need deal list size]:"+sqlList.size());
			if(sqlList.size()>this.BATCH_COMMIT_UNIT){
				ret =this.jdbc.batchUpdate(sqlList.subList(0, this.BATCH_COMMIT_UNIT).toArray(Tools.emptyArrayString));
				sqlList.removeAll(sqlList.subList(0, this.BATCH_COMMIT_UNIT));
				totalResult=totalResult+ret.length;
			}else{
				ret =this.jdbc.batchUpdate(sqlList.toArray(Tools.emptyArrayString));
				totalResult=totalResult+ret.length;
				sqlList=null;
				break;
			}
		}
		log.info("[end batch update],result:"+totalResult);
		return ret.length;
	}


	public Integer getStart() {
		return start;
	}

	public void setStart(Integer start) {
		this.start = start;
	}

	public Integer getLimit() {
		return limit;
	}

	public void setLimit(Integer limit) {
		this.limit = limit;
	}

	public List<String> getSort() {
		return sort;
	}

	public void setSort(Object sort) {
		if (sort instanceof Object[]) {
			Object[] t = (Object[]) sort;
			List<String> l = new ArrayList<String>();
			for (Object o : t) {
				l.add(o.toString());
			}
			this.setSort(l);
		} else {
			this.setSort(sort.toString());
		}
	}

	public void setSort(String sort) {
		this.sort = new ArrayList<String>();
		this.sort.add(sort);
	}

	public void setSort(List<String> sort) {
		this.sort = sort;
	}

	public void setDir(Object dir) {
		if (dir instanceof Object[]) {
			Object[] t = (Object[]) dir;
			List<String> l = new ArrayList<String>();
			for (Object o : t) {
				l.add(o.toString());
			}
			this.setDir(l);
		} else {
			this.setDir(dir.toString());
		}
	}

	public void setDir(String dir) {
		this.dir = new ArrayList<String>();
		this.dir.add(dir);
	}

	public List<String> getDir() {
		return dir;
	}

	public void setDir(List<String> dir) {
		this.dir = dir;
	}

	public JdbcTemplate getJdbc() {
		return jdbc;
	}

	public void setJdbc(JdbcTemplate jdbc) {
		this.jdbc = jdbc;
	}

}
